package com.etoak.stock.service.impl;

import com.etoak.stock.config.TaskExecutePool;
import com.etoak.stock.mapper.StockBlockRtInfoMapper;
import com.etoak.stock.mapper.StockBusinessMapper;
import com.etoak.stock.mapper.StockMarketIndexInfoMapper;
import com.etoak.stock.mapper.StockRtInfoMapper;
import com.etoak.stock.pojo.entity.StockBlockRtInfo;
import com.etoak.stock.pojo.entity.StockMarketIndexInfo;
import com.etoak.stock.pojo.vo.StockInfoConfig;
import com.etoak.stock.service.StockTimerTaskService;
import com.etoak.stock.utils.DateTimeUtil;
import com.etoak.stock.utils.IdWorker;
import com.etoak.stock.utils.ParseType;
import com.etoak.stock.utils.ParserStockInfoUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author by 孙有泽
 * @Date 2024/10/139:48
 * @Description 定义采集股票数据的定时任务的服务
 */
@Service
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StockInfoConfig stockInfoConfig;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;

    private  HttpEntity<Object> httpEntity;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /*
     * @author 孙有泽
     * @date 2024/10/27 14:36
     * @description 获取国内大盘的实时数据信息
     */
    @Override
    public void getInnerMarketInfo() {
        //1.采集原始数据
        //组装url地址 http://hq.sinajs.cn/list=sh000001,sz399001
        String url=stockInfoConfig.getMarketUrl()+String.join(",",stockInfoConfig.getInner());
        //维护请求头 添加防盗链和用户标识
/*        HttpHeaders httpHeaders = new HttpHeaders();
        //防盗链
        httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
        //用户标识
        httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //维护http请求实体对象
        HttpEntity<Object> httpEntity = new HttpEntity<>(httpHeaders);*/
        //发送请求获取数据
        ResponseEntity<String> httpExchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        int statusCodeValue = httpExchange.getStatusCodeValue();
        if(statusCodeValue!=200){
            log.error("当前采集国内盘股票数据失败:{}，状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),statusCodeValue);
            return;
        }
        String body = httpExchange.getBody();
        //使用java正则解析数据
        //定义正则表达式
        String reg="var hq_str_(.+)=\"(.+)\";";
        //表达式编译
        Pattern pattern = Pattern.compile(reg);
        //取配字符串
        Matcher matcher = pattern.matcher(body);
        List<StockMarketIndexInfo> entityList = new ArrayList<>();
        while (matcher.find()){
            String marketCode = matcher.group(1);
            String other= matcher.group(2);
            String[] splitArr = other.split(",");
            //大盘名称
            String marketName=splitArr[0];
            //获取当前大盘的开盘点数
            BigDecimal openPoint=new BigDecimal(splitArr[1]);
            //前收盘点
            BigDecimal preClosePoint=new BigDecimal(splitArr[2]);
            //获取大盘的当前点数
            BigDecimal curPoint=new BigDecimal(splitArr[3]);
            //获取大盘最高点
            BigDecimal maxPoint=new BigDecimal(splitArr[4]);
            //获取大盘的最低点
            BigDecimal minPoint=new BigDecimal(splitArr[5]);
            //获取成交量
            Long tradeAmt=Long.valueOf(splitArr[8]);
            //获取成交金额
            BigDecimal tradeVol=new BigDecimal(splitArr[9]);
            //时间
            Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
            //组装entity对象
            StockMarketIndexInfo entity = StockMarketIndexInfo.builder()
                    .id(idWorker.nextId())
                    .marketName(marketName)
                    .openPoint(openPoint)
                    .preClosePoint(preClosePoint)
                    .curPoint(curPoint)
                    .maxPoint(maxPoint)
                    .minPoint(minPoint)
                    .tradeAmount(tradeAmt)
                    .tradeVolume(tradeVol)
                    .marketCode(marketCode)
                    .curTime(curTime)
                    .build();
            entityList.add(entity);
        }
        //数据批量入库
        int count=stockMarketIndexInfoMapper.insertBatch(entityList);
        if(count>0){
            //大盘数据采集完毕后 通知backend工程刷新缓存
            //发送日期对象,接受方通过接受日期的比例，能判断出数据延迟的时长，用于运维通知处理
            rabbitTemplate.convertAndSend("stockExchange","inner.market",new Date());
           log.info("当前采集国内大盘数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
        }
    }
    /*
     * @param null
     * @return null
     * @author 孙有泽
     * @date 2024/10/13 15:45
     * @description 定义获取分钟级股票数据
     */
    @Override
    public void getStockRtIndex() {
        //获取所有个股的集合
        List<String> stockIds = stockBusinessMapper.getStockIds();
        //添加大盘业务前缀 sh sz
        stockIds = stockIds.stream().map(code -> code.startsWith("6") ? "sh" + code : "sz" + code).collect(Collectors.toList());
        //将大的集合切成若干个小集合 分批次拉取数据
        Lists.partition(stockIds, 15).forEach(codes->{
           // String url=stockInfoConfig.getMarketUrl()+String.join(",",codes);
           /* //维护请求头 添加防盗链和用户标识
            HttpHeaders httpHeaders = new HttpHeaders();
            //防盗链
            httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
            //用户标识
            httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
            //维护http请求实体对象
            HttpEntity<Object> httpEntity = new HttpEntity<>(httpHeaders);*/
            //发送请求获取数据
            //ResponseEntity<String> httpExchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
           // int statusCodeValue = httpExchange.getStatusCodeValue();
            /*if(statusCodeValue!=200){
                log.error("当前采集国内盘股票数据失败:{}，状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),statusCodeValue);
                return;
            }*/
            //String body = httpExchange.getBody();
            //调用工具类解析获取各个数据
        /*    List list = parserStockInfoUtil.parser4StockOrMarketInfo(body, ParseType.ASHARE);
            log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),list);
            int count=stockRtInfoMapper.insertBatch(list);
            System.out.println(count);
            if(count>0){
                log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),count);
            }*/
    /*        new Thread(()->{
                 String url=stockInfoConfig.getMarketUrl()+String.join(",",codes);
           *//* //维护请求头 添加防盗链和用户标识
            HttpHeaders httpHeaders = new HttpHeaders();
            //防盗链
            httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
            //用户标识
            httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
            //维护http请求实体对象
            HttpEntity<Object> httpEntity = new HttpEntity<>(httpHeaders);*//*
                //发送请求获取数据
                ResponseEntity<String> httpExchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
                 int statusCodeValue = httpExchange.getStatusCodeValue();
            if(statusCodeValue!=200){
                log.error("当前采集国内盘股票数据失败:{}，状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),statusCodeValue);
                return;
            }
            String body = httpExchange.getBody();
                //调用工具类解析获取各个数据
            List list = parserStockInfoUtil.parser4StockOrMarketInfo(body, ParseType.ASHARE);
            log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),list);
            int count=stockRtInfoMapper.insertBatch(list);
            System.out.println(count);
            if(count>0){
                log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),count);
            }
            }).start();*/
            threadPoolTaskExecutor.execute(()->{
                String url=stockInfoConfig.getMarketUrl()+String.join(",",codes);
                //维护请求头 添加防盗链和用户标识
       /*         HttpHeaders httpHeaders = new HttpHeaders();
                //防盗链
                httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
                //用户标识
                httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
                //维护http请求实体对象
                HttpEntity<Object> httpEntity = new HttpEntity<>(httpHeaders);*/
                //发送请求获取数据
                ResponseEntity<String> httpExchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
                int statusCodeValue = httpExchange.getStatusCodeValue();
                if(statusCodeValue!=200){
                    log.error("当前采集国内盘股票数据失败:{}，状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),statusCodeValue);
                    return;
                }
                String body = httpExchange.getBody();
                //调用工具类解析获取各个数据
                List list = parserStockInfoUtil.parser4StockOrMarketInfo(body, ParseType.ASHARE);
                log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),list);
                int count=stockRtInfoMapper.insertBatch(list);
                System.out.println(count);
                if(count>0){
                    log.info("当前采集国内盘股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),count);
                }
            });
        });

    }

    @Override
    public void getStockBlockInfo() {
        String blockUrl = stockInfoConfig.getBlockUrl();
        ResponseEntity<String> httpExchange = restTemplate.exchange(blockUrl, HttpMethod.GET, httpEntity, String.class);
        int  statusCode = httpExchange.getStatusCodeValue();
        if(statusCode!=200){
            log.error("当前采集国内板块股票数据失败:{}，状态码：{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),statusCode);
            return;
        }
        String body = httpExchange.getBody();
        List<StockBlockRtInfo> stockBlockRtInfos = parserStockInfoUtil.parse4StockBlock(body);
        int count=stockBlockRtInfoMapper.insertBatch(stockBlockRtInfos);
        if(count>0){
            log.info("当前采集国内板块股票数据成功，时间：{}，数据量：{}",DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),count);
        }


    }

    /*
        定义bean声明周期的初始化回调方法
    */
    @PostConstruct
    public void initData(){
        //维护请求头 添加防盗链和用户标识
        HttpHeaders httpHeaders = new HttpHeaders();
        //防盗链
        httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
        //用户标识
        httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //维护http请求实体对象
        httpEntity = new HttpEntity<>(httpHeaders);
    }
}
